﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;
using System.Configuration;

namespace InvoiceInvoker.Logic.Repositories
{
	public class InvoicePatternRepository : InvoiceInvoker.Logic.RepositoryInterfaces.IInvoicePatternRepository
	{
		private string _connectionString;
		private int _registeredSellerId;
		private DataLoadOptions _loadOptions;

		public InvoicePatternRepository(int registeredSellerId)
		{
			_connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;

			this._registeredSellerId = registeredSellerId;

			_loadOptions = new DataLoadOptions();
			_loadOptions.LoadWith<InvoicePattern>(x => x.RegisteredCustomer);
			_loadOptions.LoadWith<InvoicePattern>(x => x.RegisteredSeller);
			_loadOptions.LoadWith<InvoicePattern>(x => x.InvoicePatternRegisteredProducts);
			_loadOptions.LoadWith<InvoicePatternRegisteredProduct>(x => x.RegisteredProduct);
		}

		public List<InvoicePattern> GetAll()
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.LoadOptions = _loadOptions;
				var query = from pattern in dataContext.InvoicePatterns
							where pattern.RegisteredSellerId == _registeredSellerId
							orderby pattern.RegisteredCustomer.CompanyName ascending
							select pattern;
				return query.ToList();
			}
		}

		public List<InvoicePattern> GetByCustomer(string companyName)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.LoadOptions = _loadOptions;
				var query = from pattern in dataContext.InvoicePatterns
							where pattern.RegisteredSellerId == _registeredSellerId &&
								  pattern.RegisteredCustomer.CompanyName.StartsWith(companyName)
							orderby pattern.RegisteredCustomer.CompanyName ascending
							select pattern;
				return query.ToList();
			}
		}

		public List<InvoicePattern> GetByProduct(string productName)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.LoadOptions = _loadOptions;
				var query = from pattern in dataContext.InvoicePatterns
							where pattern.RegisteredSellerId == _registeredSellerId &&
								  pattern.InvoicePatternRegisteredProducts.Any(x => x.RegisteredProduct.Name.StartsWith(productName))
							orderby pattern.RegisteredCustomer.CompanyName ascending
							select pattern;
				return query.ToList();
			}
		}

		public List<InvoicePattern> GetByExpression(Func<InvoicePattern, bool> expression)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.LoadOptions = _loadOptions;
				var mainQuery = from pattern in dataContext.InvoicePatterns
								where pattern.RegisteredSellerId == _registeredSellerId
								orderby pattern.RegisteredCustomer.CompanyName ascending
								select pattern;
				return mainQuery.Where(expression).ToList();
			}
		}

		public InvoicePattern GetById(int id)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.LoadOptions = _loadOptions;
				return dataContext.InvoicePatterns.SingleOrDefault(pattern => pattern.Id == id);
			}
		}

		public void Add(InvoicePattern item)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.InvoicePatterns.InsertOnSubmit(item);
				dataContext.SubmitChanges();
			}
		}

		public void Add(InvoicePattern item, IEnumerable<int> registeredProductIds)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				foreach (int id in registeredProductIds)
				{
					InvoicePatternRegisteredProduct entity = new InvoicePatternRegisteredProduct();
					entity.InvoicePattern = item;
					entity.RegisteredProductId = id;
					dataContext.InvoicePatternRegisteredProducts.InsertOnSubmit(entity);
				}

				dataContext.SubmitChanges();
			}
		}

		public void Add(InvoicePattern item, IEnumerable<RegisteredProduct> products)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				foreach (RegisteredProduct product in products)
				{
					InvoicePatternRegisteredProduct entity = new InvoicePatternRegisteredProduct();
					entity.InvoicePattern = item;
					if (product.Id == 0)
						entity.RegisteredProduct = product;
					else
						entity.RegisteredProductId = product.Id;
					dataContext.InvoicePatternRegisteredProducts.InsertOnSubmit(entity);
				}

				dataContext.SubmitChanges();
			}
		}

		public void Remove(int itemId)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				DataLoadOptions loadOptions = new DataLoadOptions();
				loadOptions.LoadWith<InvoicePattern>(pattern => pattern.InvoicePatternRegisteredProducts);
				var query = from pattern in dataContext.InvoicePatterns where pattern.Id == itemId select pattern;

				InvoicePattern invoicePattern = query.SingleOrDefault();

				dataContext.InvoicePatterns.DeleteOnSubmit(invoicePattern);
				dataContext.InvoicePatternRegisteredProducts.DeleteAllOnSubmit(invoicePattern.InvoicePatternRegisteredProducts);

				dataContext.SubmitChanges();
			}
		}

		public void Update(InvoicePattern item)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.InvoicePatterns.Attach(item, GetById(item.Id));
				dataContext.SubmitChanges();
			}
		}

		public void Update(InvoicePattern pattern, List<int> registeredProductIds)
		{
			using (MainDataContext dataContext = new MainDataContext(_connectionString))
			{
				dataContext.InvoicePatterns.Attach(pattern, GetById(pattern.Id));

				foreach (var item in pattern.InvoicePatternRegisteredProducts)
				{
					if (registeredProductIds.Contains(item.RegisteredProductId.Value) == false)
						dataContext.InvoicePatternRegisteredProducts.DeleteOnSubmit(item);
					else
						registeredProductIds.Remove(item.RegisteredProductId.Value);
				}

				foreach (int id in registeredProductIds)
				{
					InvoicePatternRegisteredProduct entity = new InvoicePatternRegisteredProduct();
					entity.InvoicePatternId = pattern.Id;
					entity.RegisteredProductId = id;
					dataContext.InvoicePatternRegisteredProducts.InsertOnSubmit(entity);
				}

				dataContext.SubmitChanges();
			}
		}
	}
}
